package com.aaa.tars.service.impl;

import com.aaa.tars.dao.UserDao;
import com.aaa.tars.entity.LoginLog;
import com.aaa.tars.entity.Role;
import com.aaa.tars.entity.ModifyPwd;
import com.aaa.tars.entity.User;
import com.aaa.tars.service.LoginLogService;
import com.aaa.tars.service.UserService;
import com.aaa.tars.util.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import net.bytebuddy.implementation.bytecode.Throw;
import org.apache.shiro.crypto.hash.Sha512Hash;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 用户信息服务实现类
 * 实现用户相关的业务逻辑处理，包括用户登录、登出、密码修改等核心功能
 * 处理用户身份验证、会话管理、密码安全等业务逻辑
 *
 * @author makejava
 * @since 2025-07-09 16:46:25
 */
@Service("userService")
public class UserServiceImpl implements UserService {
    @Resource
    private UserDao userDao;
//    private final static String Del_FLAG = "0";

    @Resource
    private LoginLogService loginLogService;
    @Resource
    private HttpSession session;

    /**
     * 用户登录验证
     * 该方法负责处理用户登录验证的完整流程，包括用户名查询、密码验证、会话管理等操作
     * 使用SHA512算法进行密码安全验证
     * 
     * @param userName 用户名
     * @param password 密码
     * @return Result 登录结果
     */
    @Override
    public Result checkUser(String userName, String password) {
        User user =new User();
        // 设置用户名
        user.setUserName(userName);
        // 设置
        // 用户状态和删除标识
        user.setStatus("0");
        user.setDelFlag("0");
        //根据上面条件查询到用户列表
        List<User> userList = userDao.queryAllByLimit(user);
        //判断不为null，继续
        if(!CollectionUtils.isEmpty(userList)){
            //获取用户
            User userInfo = userList.get(0);
            //1	1	管理员	admin	86521760@qq.com	18538062907	0	https://wangzherongyao.oss-cn-beijing.aliyuncs.com/upload/files/1605770604552-7c5b7014-09cb-4d0a.jpg	23279b2423d5f458fa443763bae48710820e80f45c07bbad63316246a26eb05e16d364780e407a2a42cf93be6f19066673b9a6a81c700198f062a0b4c019db82	fab6035c-2597-462b-a301-0d6110a6799b	0	0	172.16.22.53	2020-08-25 14:55:54	admin	2019-11-19 11:33:00	ry	2019-12-28 15:05:05	管理员
            //获取盐值  随机字符串  salt=fab6035c-2597-462b-a301-0d6110a6799b
            String salt = userInfo.getSalt();
            //获取加密密码  passwordDb=23279b2423d5f458fa443763bae48710820e80f45c07bbad63316246a26eb05e16d364780e407a2a42cf93be6f19066673b9a6a81c700198f062a0b4c019db82
            String passwordDb = userInfo.getPassword();
            //加密算法  SHA安全散列算法（英语：Secure Hash Algorithm，缩写为SHA）
            //https://baike.baidu.com/item/SHA%E5%AE%B6%E6%97%8F/9849595
            //Object source, Object salt, int hashIterations
            //      原密码          盐值                                      hash迭代次数
            //      tiger     fab6035c-2597-462b-a301-0d6110a6799b           1024
            //再次使用tiger原始密码再次进行加密运算
            Sha512Hash sha512Hash = new Sha512Hash(password,salt,1024);
            //计算后的密码就是 23279b2423d5f458fa443763bae48710820e80f45c07bbad63316246a26eb05e16d364780
            String passwordSHA = sha512Hash.toString();
            //再次对比密码
            if(passwordSHA.equals(passwordDb)){
                //向session存入用户信息
                session.setAttribute("userInfo",userInfo);
                return ResultUtil.success("登录成功");
            }else {
                throw new RuntimeException("密码错误");
            }
        }else {
            throw new RuntimeException("用户不存在");
        }
    }


    @Override
    public Result logout(HttpSession session) {
        //判断session不为null
        if(session!=null){
            // 获取当前登录用户信息
            User user = (User) session.getAttribute("userInfo");

            if (user != null) {
                LoginLog loginLog1 = new LoginLog();
                loginLog1.setUserName(user.getUserName());
                loginLog1.setLoginStatus(0);
                // 查询最近一次登录记录
                List<LoginLog> loginLogList = loginLogService.queryAllByLimit(loginLog1);

                if(!CollectionUtils.isEmpty(loginLogList)){
                    LoginLog loginLog = loginLogList.get(0);

                    if (loginLog.getLoginTime() != null) {
                        // 设置登出时间
                        loginLog.setLogOutTime(new Date());
                        // 更新登录日志记录
                        loginLogService.update(loginLog);
                    }
                }
            }

            //清除登录信息
            session.removeAttribute("userInfo");
            //清除session
            session.invalidate();
            return ResultUtil.success("退出成功");
        }
        return ResultUtil.error("退出失败");
    }

    /**
     * 更新用户密码
     * 该方法负责处理用户密码修改的完整流程，包括旧密码验证、新密码一致性检查、
     * 密码加密、盐值更新等安全操作
     *
     * @param mpwd 包含旧密码、新密码和确认密码的ModifyPwd对象
     * @param userId 用户ID
     * @return Result操作结果对象，包含操作成功或失败的信息
     */
    @Override
    public Result updatePassword(ModifyPwd mpwd, Integer userId) {
        //打印输入修改密码
        System.out.println("输入修改密码："+mpwd);
        // 验证新密码与确认密码是否一致
        if(!mpwd.getNewPassword().equals(mpwd.getConfirmPassword())) {
            return ResultUtil.error("两次输入密码不一致");
        }

        // 根据用户ID查询用户信息
        User user = userDao.queryById(userId);
        // 获取用户当前的盐值
        String salt = user.getSalt();
        // 使用SHA512算法和原有盐值对用户输入的旧密码进行加密
        Sha512Hash sha512Hash = new Sha512Hash(mpwd.getOldPassword(), salt, 1024);
        // 验证用户输入的旧密码是否正确
        if(!sha512Hash.toString().equals(user.getPassword())) {
            return ResultUtil.error("原密码错误");
        }

        // 生成新的盐值用于新密码加密
        String newSalt = UUID.randomUUID().toString();
        // 使用SHA512算法和新盐值对新密码进行加密
        String newPassword = new Sha512Hash(mpwd.getNewPassword(), newSalt, 1024).toString();

        // 创建更新用户对象
        User updateUser = new User();
        // 设置用户ID
        updateUser.setUserId(userId);
        // 设置新的盐值
        updateUser.setSalt(newSalt);
        // 设置新的加密密码
        updateUser.setPassword(newPassword);
        // 执行更新操作
        update(updateUser);

        return ResultUtil.success("密码修改成功");
    }

    /**
     * 通过ID查询单条数据
     *
     * @param userId 主键
     * @return 实例对象
     */
    @Override
    public User queryById(Integer userId) {
        return this.userDao.queryById(userId);
    }

    /**
     * 分页查询
     *
     * @param page 筛选条件
     * @return 查询结果
     */
    @Override
    public PageInfo queryByPage(Page<User> page) {
        //分页操作  分页参数一定要进行传递
        if (page == null || page.getPageNo() == null || page.getPageNo() == 0 || page.getPageSize() == null || page.getPageSize() == 0) {
            //进行业务编写时，可以抛出自定义异常
            throw new CustomException(ResultStatus.ARGUMENT_ERROR.getStatusCode(),
                    ResultStatus.ARGUMENT_ERROR.getStatusMessage());
        }
        PageHelper.startPage(page.getPageNo(), page.getPageSize());
        //获取查询对象
        User user = page.getData();
        return new PageInfo(userDao.queryAllByLimit(user));
    }

    /**
     * 新增数据
     *
     * @param user 实例对象
     * @return 实例对象
     */
    @Override
    public User insert(User user) {
        // 如果密码为空，设置默认密码
        if (user.getPassword() == null || user.getPassword().isEmpty()) {
            user.setPassword("123456");
        }
        // 获取原始密码
        String oldPassword = user.getPassword();
        // 随机获取盐值
        String salt = UUID.randomUUID().toString();
        // 使用shiro提供的加密算法，计算新密码
        String newPassword = new Sha512Hash(oldPassword, salt, 1024).toString();
        // 设置盐值和密码
        user.setSalt( salt);
        user.setPassword(newPassword);
        // 设置添加时间
        user.setCreateTime(new Date());
        // 设置账号状态
        user.setStatus("0");
        // 设置账号删除标识
        user.setDelFlag("0");

        //动态获取创建人
        //拿到登录session
        User userInfo = (User) session.getAttribute("userInfo");
        user.setCreateBy(userInfo.getUserName());

        this.userDao.insert(user);
        return user;
    }

    /**
     * 修改数据
     *
     * @param user 实例对象
     * @return 实例对象
     */
    @Override
    public User update(User user) {
        user.setUpdateTime(new Date());

        //动态获取创建人
        //拿到登录session
        User userInfo = (User) session.getAttribute("userInfo");
        user.setUpdateBy(userInfo.getUserName());
        
        this.userDao.update(user);
        return this.queryById(user.getUserId());
    }

    /**
     * 通过主键删除数据
     *
     * @param userId 主键
     * @return 是否成功
     */
    @Override
    public boolean deleteById(Integer userId) {
        //用户名为111，删除失败
        if ("admin".equals(this.queryById(userId).getUserName())) {
            throw new CustomException(1030,"不能删除超级管理员");
        }
        return this.userDao.deleteById(userId) > 0;
    }

    //获取用户角色
    @Override
    public List<Role> getRolesByUserId(Integer userId) {
        // 查询数据库，若无结果返回空列表
        List<Role> roles = userDao.selectRolesByUserId(userId);
        return roles != null ? roles : new ArrayList<>();
    }

    @Override
    public void assignRoles(Integer userId, List<Integer> roleIds) {
        // 先删除旧的关联
        userDao.deleteUserRole(userId); // 清空所有角色

        // 再插入新的角色
        for (Integer roleId : roleIds) {
            userDao.insertUserRole(userId, roleId);
        }
    }


}
